package core;

/**
 * Represents a collection of cards. Note that <code>defaultVisibility</code>
 * and <code>defaultLocation</code> do not get applied automatically as cards
 * are added, because actions must be atomic for automatic undo to work.
 */
public class Zone extends GameObject
{
	public Zone(String name) {
		this(name, DEFAULT_DEFAULT_VISIBILITY, DEFAULT_DEFAULT_LOCATION);
	}

	public Zone(String name, Visibility defaultVisibility) {
		this (name, defaultVisibility, DEFAULT_DEFAULT_LOCATION);
	}

	public Zone(String name, Location defaultLocation) {
		this(name, DEFAULT_DEFAULT_VISIBILITY, defaultLocation);
	}

	public Zone(String name, Visibility defaultVisibility, Location defaultLocation)
	{
		super(name);
		this.defaultVisibility = defaultVisibility;
		this.defaultLocation = defaultLocation;
		childrens.add(java.util.Collections.unmodifiableList(cards));
	}

	/**
	 * Adds a card to this zone.
	 * @param card the card to be added
	 * @return the card that was added
	 */
	public Card addCard(Card card)
	{
		cards.add(card);
		card.setZone(this);
		onAdd(card);
		return card;
	}

	/**
	 * Removes a card from this zone.
	 * @param card the card to remove
	 * @return true iff the remove operation was successful
	 */
	public boolean removeCard(Card card)
	{
		if (cards.contains(card))
		{
			cards.remove(card);
			card.setZone(null);
			onRemove(card);
			return true;
		}
		return false;
	}
	
	/**
	 * Removes all cards from this zone.
	 */
	public void removeAllCards() {
		for (Card c: cards)
			removeCard(c);
	}

	/**
	 * Returns an unmodifiable view of the cards in this zone.
	 */
	public java.util.Collection<Card> getCards() {
		return java.util.Collections.unmodifiableList(cards);
	}

	public Visibility getDefaultVisibility() {
		return defaultVisibility;
	}

	public Location getDefaultLocation() {
		return defaultLocation;
	}

	/**
	 * Adds a ZoneObserver to be notified of zone events.
	 */
	public void addZoneObserver(ZoneObserver observer) {
		zoneObservers.add(observer);
	}

	/**
	 * Removes the given ZoneObserver from the notification list.
	 */
	public void removeZoneObserver(java.util.Observer observer) {
		zoneObservers.remove(observer);
	}

	/**
	 * Called when a card is added to the zone.
	 * @param card the Card that was added
	 */
	protected void onAdd(Card card) {
		for (ZoneObserver zoneObserver : zoneObservers)
			zoneObserver.cardAdded(card);
	}

	/**
	 * Called when a card is removed from the zone.
	 * @param card the removed Card
	 */
	protected void onRemove(Card card) {
		for (ZoneObserver zoneObserver : zoneObservers)
			zoneObserver.cardRemoved(card);
	}

	protected final Visibility defaultVisibility;
	protected final static Visibility DEFAULT_DEFAULT_VISIBILITY = Visibility.NONE;

	protected final Location defaultLocation;
	protected final static Location DEFAULT_DEFAULT_LOCATION = new Location(0, 0, 0f);
	
	protected final java.util.List<ZoneObserver> zoneObservers = new java.util.LinkedList<ZoneObserver>();
	protected final java.util.List<Card> cards = new java.util.LinkedList<Card>();
}
